/*
*
==============================================================================
*  Name        : 
*  Part of     : Omen Game Engine
*  Description : 
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#pragma once

#include "OmenConfig.h"

#include "OmenDataTypes.h"
#include "OmenMath.h"

namespace Omen
{
    class OMEN_API IBoundingVolume 
    {
    public:
        typedef enum
        {
            BoundingVolume_Sphere,
            BoundingVolume_AABB
        } BoundingVolumeType;

        IBoundingVolume( BoundingVolumeType type ) : m_volumeType(type) {};
        virtual bool collides( IBoundingVolume* pVolume ) = 0;
        
        BoundingVolumeType volumeType() const { return m_volumeType; }

    protected:
        BoundingVolumeType  m_volumeType;
    private:
    };

    ///
    /// Sphere bounding volume
    ///
    class OMEN_API SphereBoundingVolume : public IBoundingVolume
    {
    public:
        SphereBoundingVolume( const Omen::Vector3d& position = Omen::Vector3d(0.0,0.0,0.0), Omen::Float radius = 0.0 );
        SphereBoundingVolume( const SphereBoundingVolume& other ) : IBoundingVolume(BoundingVolume_Sphere), m_sphere(other.m_sphere) {}
        virtual bool collides( IBoundingVolume* pVolume );

        inline Omen::Vector3d  position() const { return m_sphere.position(); }
        inline Omen::Float     radius() const { return m_sphere.radius(); }
        void setPosition( const Omen::Vector3d& position ) { m_sphere.setPosition(position); }
        void setRadius( const Omen::Float radius ) { m_sphere.setRadius(radius); }
    protected:
    private:
        Omen::Sphere    m_sphere;
    };

    ///
    /// Axis aligned bounding box volume
    ///
    class OMEN_API AABBVolume : public IBoundingVolume
    {
    public:
        AABBVolume( const Omen::Vector3d& min = Omen::Vector3d(0.0,0.0,0.0), const Omen::Vector3d& max = Omen::Vector3d(0.0,0.0,0.0) ) : IBoundingVolume(BoundingVolume_AABB),m_aabb(min,max) {};
        AABBVolume( const AABBVolume& other ) : IBoundingVolume(BoundingVolume_AABB), m_aabb(other.m_aabb) {}
        virtual bool collides( IBoundingVolume* pVolume );

        const Omen::Vector3d& vmin() const { return m_aabb.minimum(); }
        const Omen::Vector3d& vmax() const { return m_aabb.maximum(); }
    protected:
    private:
        Omen::AABB m_aabb;
    };
    ///
    /// Interface for object to object collision detection
    ///
    class OMEN_API ICollidable
    {
    public:
        virtual bool testCollision( ICollidable** pListObjects, unsigned long maxNum ) = 0;
    protected:
    private:        
    };
}

OMEN_API bool SphereToSphere( const Omen::SphereBoundingVolume& sphere1, const Omen::SphereBoundingVolume& sphere2 ); 
OMEN_API bool SphereToAABB(const Omen::SphereBoundingVolume& sphere, const Omen::AABBVolume& box );
OMEN_API bool AABBtoAABB(const Omen::AABBVolume& box1, const Omen::AABBVolume& box2);
OMEN_API Omen::Float intersectRayPlane(Omen::Vector3d& rOrigin, Omen::Vector3d& rVector, Omen::Vector3d& pOrigin, Omen::Vector3d& pNormal);